 package com.flirc
{
	import flash.events.*;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	
	public class IRCSocket extends Socket
	{
		public var onSockRead:Function;
		public var onSockOpen:Function;
		public var onSockError:Function;
		public var onSockClose:Function;
		public var onSockWrite:Function;
		
		private var _charset:String;
		private var input:ByteArray;
		
		public function IRCSocket(charset:String = 'utf-8', host:String = null, port:uint = 0)
		{		
			super(host, port);
			
			addEventListener(Event.CONNECT, onConnect);
			addEventListener(ProgressEvent.SOCKET_DATA, onRead);
			addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			addEventListener(IOErrorEvent.IO_ERROR, onIOError);
		
			_charset = charset;
			input = new ByteArray();
		}
		
		private function onConnect(event:Event):void
		{
			onSockOpen(event);
		}
		
		private function onRead(event:ProgressEvent):void
		{
			while (bytesAvailable > 0)
			{
				var byte:uint = readUnsignedByte();
				var next:uint;
				
				if (byte == 13)
				{
					if (bytesAvailable >= 1)
					{
						next = readUnsignedByte();
						
						if (next == 10)
						{
							input.position = 0;
							onSockRead(input.readMultiByte(input.length, _charset));
							input.clear();
						}
						else
						{
							input.writeByte(byte);
							input.writeByte(next);
						}
					}
					else
						input.writeByte(byte);
				}
				else
					input.writeByte(byte);
			}
		}
		
		private function onSecurityError(event:SecurityError):void
		{
			onSockError(event.message);
		}
		
		private function onIOError(event:IOErrorEvent):void
		{
			onSockError(event.text);
		}
		
		public function sendString(output:String):void
		{
			var array:ByteArray = new ByteArray();
			var i:int = 0;
			var j:int = output.length;
			
			array.writeMultiByte(output, _charset);
			
			array.writeByte(0x0D);
			array.writeByte(0x0A);
			
			writeBytes(array, 0, array.length);
			flush();
		}
		
		public function set charset(value:String):void
		{
			_charset = value;
		}
		
		public function get charset():String
		{
			return _charset;
		}
	}
}